package com.example.teesystem.service.impl;

import cn.hutool.core.lang.id.NanoId;
import com.example.teesystem.common.exception.Assert;
import com.example.teesystem.common.utils.PermissionUtil;
import com.example.teesystem.common.utils.ResultCode;
import com.example.teesystem.common.websocket.model.*;
import com.example.teesystem.controller.PKController;
import com.example.teesystem.entity.Issue;
import com.example.teesystem.mapper.IssueMapper;
import com.example.teesystem.service.PKService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class PKServiceImpl implements PKService {
    @Value("${tee.pk.destination}")
    private String DESTINATION;
    @Value("${tee.pk.issue-size}")
    private Integer ISSUE_SIZE;
    
    private final SimpMessagingTemplate simpMessagingTemplate;
    private final IssueMapper issueMapper;
    
    
    @Override
    public synchronized void startMatch(PKMessage pkMessage) {
        // 1. 判断玩家是否重复提交匹配请求
        UserInfo userInfo = PKController.userInfos.get(pkMessage.getUid());
        if(userInfo != null) {
            simpMessagingTemplate.convertAndSendToUser(pkMessage.getUid().toString(), DESTINATION, "正在匹配中，请勿重复提交");
            return;
        }
    
        // 2. 添加到匹配队列中
        UserInfo newUser = new UserInfo(pkMessage.getUid(), pkMessage.getCourseId(), UserType.MATCHING);
        PKController.userInfos.put(newUser.getUid(), newUser);
    
        // 3. 检查队列中是否有大于等于两个玩家正在匹配，若存在，则创建分组
        List<UserInfo> matchingUsers = this.findMatchingUsers(pkMessage.getCourseId());
        if(matchingUsers.size() == 2) {
            // 获取正在匹配的用户
            UserInfo userA = matchingUsers.get(0);
            UserInfo userB = matchingUsers.get(1);
        
            // 更新用户状态
            userA.setType(UserType.PLAYING);
            userA.setUpdateTime(LocalDateTime.now());
            userB.setType(UserType.PLAYING);
            userB.setUpdateTime(LocalDateTime.now());
        
            // 创建分组
            GroupInfo groupInfo = new GroupInfo(NanoId.randomNanoId(), userA, userB, this.getIssues(pkMessage.getCourseId()));
            PKController.groupInfos.put(groupInfo.getId(), groupInfo);
            
            // 将分组信息发送给用户
            GroupResult result = new GroupResult(groupInfo.getId(), userA.getUid(), userB.getUid(), groupInfo.getIssues().size(), groupInfo.getIssues().get(0));
            simpMessagingTemplate.convertAndSendToUser(userA.getUid().toString(), DESTINATION, result);
            simpMessagingTemplate.convertAndSendToUser(userB.getUid().toString(), DESTINATION, result);
        }
    }
    
    @Override
    public synchronized void quitMatch(PKMessage pkMessage) {
        // 从匹配队列中寻找该玩家
        UserInfo userInfo = PKController.userInfos.get(pkMessage.getUid());
        // 如果玩家存在且状态为正在匹配则移除
        if(userInfo != null && UserType.MATCHING.equals(userInfo.getType())) {
            PKController.userInfos.remove(userInfo.getUid());
            simpMessagingTemplate.convertAndSendToUser(userInfo.getUid().toString(), DESTINATION, "取消匹配成功");
        }
    }
    
    @Override
    public synchronized void answer(PKMessage pkMessage) {
        // 校验传入参数
        Assert.notNull(ResultCode.PARAMETER_MISS, pkMessage.getGroupId(), pkMessage.getCurIssue(), pkMessage.getAnswer());
        GroupInfo groupInfo = PKController.groupInfos.get(pkMessage.getGroupId());
        // 添加校验
        if (pkMessage.getCurIssue().equals(groupInfo.getCurIssue())) {
            boolean currentResult;
            if (validAnswer(pkMessage)) {
                //更新分组信息
                groupInfo.setUpdateTime(LocalDateTime.now());

                Map<Integer, Integer> answerConditions = groupInfo.getAnswerConditions();
                answerConditions.put(pkMessage.getCurIssue(), pkMessage.getUid());
                groupInfo.setAnswerConditions(answerConditions);

                currentResult = true;
                System.out.println("答对了");
            } else {
                currentResult = false;
            }

            int nextIssue = pkMessage.getCurIssue() + 1;
            groupInfo.setCurIssue(nextIssue);
            PKController.groupInfos.put(pkMessage.getGroupId(),groupInfo);

            if (nextIssue >= groupInfo.getIssues().size()) {
                end(pkMessage.getGroupId());
            } else {
                // 发送下一道题给玩家
                PkIssueMessage answerUserResult = new PkIssueMessage(groupInfo.getIssues().get(nextIssue), currentResult);
                PkIssueMessage otherUserResult = new PkIssueMessage(groupInfo.getIssues().get(nextIssue), false);

                if (pkMessage.getUid().equals(groupInfo.getUserA().getUid())) {
                    simpMessagingTemplate.convertAndSendToUser(groupInfo.getUserA().getUid().toString(), DESTINATION, answerUserResult);
                    simpMessagingTemplate.convertAndSendToUser(groupInfo.getUserB().getUid().toString(), DESTINATION, otherUserResult);
                }else {
                    simpMessagingTemplate.convertAndSendToUser(groupInfo.getUserA().getUid().toString(), DESTINATION, otherUserResult);
                    simpMessagingTemplate.convertAndSendToUser(groupInfo.getUserB().getUid().toString(), DESTINATION, answerUserResult);
                }
            }
        }

    }
    
    @Override
    public synchronized void end(String groupId) {
        GroupInfo groupInfo = PKController.groupInfos.get(groupId);
        List<Issue> pkIssueList = groupInfo.getIssues();
    
        List<PKResultMessage> userAResult = new ArrayList<>();
        List<PKResultMessage> userBResult = new ArrayList<>();
        System.out.println("********************************************************");
        System.out.println(PKController.groupInfos.get(groupId));
        int i = 0;
        // 统计答题情况
        for (Issue issue : pkIssueList){
            if (groupInfo.getAnswerConditions().get(i) == null){
                userAResult.add(new PKResultMessage(issue, false));
                userBResult.add(new PKResultMessage(issue, false));
            }else if (groupInfo.getAnswerConditions().get(i).equals(groupInfo.getUserA().getUid())){
                userAResult.add(new PKResultMessage(issue, true));
                userBResult.add(new PKResultMessage(issue, false));
            }else {
                userAResult.add(new PKResultMessage(issue, false));
                userBResult.add(new PKResultMessage(issue, true));
            }
            i++;
        }
        System.out.println("********************************************************");
        System.out.println(userAResult);
        System.out.println(userBResult);
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put(groupInfo.getUserA().getUid().toString(),userAResult);
        resultMap.put(groupInfo.getUserB().getUid().toString(),userBResult);
        // 将结果返回给用户
        simpMessagingTemplate.convertAndSendToUser(groupInfo.getUserA().getUid().toString(), DESTINATION, resultMap);
        simpMessagingTemplate.convertAndSendToUser(groupInfo.getUserB().getUid().toString(), DESTINATION, resultMap);
        
        // 移除分组和用户
        PKController.groupInfos.remove(groupInfo.getId());
        PKController.userInfos.remove(groupInfo.getUserA().getUid());
        PKController.userInfos.remove(groupInfo.getUserB().getUid());

        System.out.println("释放了链接");
    }
    
    @Override
    public void disconnect(Integer uid) {
        List<GroupInfo> groupInfos = PKController.groupInfos.values().stream()
                .filter(groupInfo -> {
                    UserInfo userA = groupInfo.getUserA();
                    UserInfo userB = groupInfo.getUserB();
                    return userA.getUid().equals(uid) || userB.getUid().equals(uid);
                })
                .collect(Collectors.toList());
        this.end(groupInfos.get(0).getId());
    }
    
    /**
     * 寻找正在匹配的玩家
     * @param courseId 课程 id
     * @return 正在匹配的玩家
     */
    private List<UserInfo> findMatchingUsers(Integer courseId) {
        return PKController.userInfos.values().stream()
                .filter(userInfo -> courseId.equals(userInfo.getCourseId()) && UserType.MATCHING.equals(userInfo.getType()))
                .limit(2)
                .collect(Collectors.toList());
    }
    
    /**
     * 随机抽题
     * @param courseId 课程 id
     * @return 该课程下的随机题列表
     */
    private List<Issue> getIssues(Integer courseId) {
        return issueMapper.getPkIssues(courseId, ISSUE_SIZE);
    }
    
    /**
     * 判断玩家答案是否正确
     * @param pkMessage
     * @return
     */
    private Boolean validAnswer(PKMessage pkMessage) {
        Issue issue = PKController.groupInfos.get(pkMessage.getGroupId()).getIssues().get(pkMessage.getCurIssue());
//        String answer = StringUtils.join(pkMessage.getAnswer(), '$');
        String answer = pkMessage.getAnswer();
        
        String[] realAnswers = issue.getAnswer().toUpperCase().split("\\$");
        String[] studentAnswers = answer.toUpperCase().split("\\$");
        
        if (realAnswers.length != studentAnswers.length){
            return false;
        }else {
            List<String> rightAnswer = Arrays.asList(realAnswers);
            boolean judge = true;
            for (String s:studentAnswers){
                if(!rightAnswer.contains(s)){
                    judge = false;
                    break;
                }
            }
            return judge;
        }
    }
}
